package org.weso.lodin.appserv;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.weso.lodin.dao.CountryDAO;
import org.weso.lodin.dao.ObservationDAO;
import org.weso.lodin.dao.WorldBankDataDAO;
import org.weso.lodin.dao.WorldBankDataDAOImpl;
import org.weso.lodin.generated.Dataset;
import org.weso.lodin.to.CompleteModelTO;
import org.weso.lodin.to.CountryTO;
import org.weso.lodin.to.DatasetTO;
import org.weso.lodin.to.ObservationTO;
import org.weso.lodin.utils.StatusUtils;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.DCTerms;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;

public class WorldBankAppServ {

	protected static Logger logger = Logger.getLogger(WorldBankAppServ.class);
	private CountryDAO daoCountries;
	private WorldBankDataDAO dao;

	public WorldBankAppServ(WorldBankDataDAO dao, CountryDAO daoCountries){
		this.dao = dao;
		this.daoCountries = daoCountries;
		
	}
	public CompleteModelTO createRDFModelFromDataset(List<String> sources) {
		List<ObservationTO> observations = this.dao.getObservations(sources);
		TransformerAppServ.decorateCountriesWB(this.daoCountries,observations);
		return observationsAsRDF(observations,null, null);
	}

	private CompleteModelTO observationsAsRDF(List<ObservationTO> observations,
			Map<String, DatasetTO> datasetsInfo, Dataset currentDataset) {
		CompleteModelTO completeModel = new CompleteModelTO();
		Model model =ModelFactory.createDefaultModel();
		Resource obs = model.createResource("http://purl.org/linked-data/cube#Observation");
		Resource weso = model.createResource(TransformerAppServ.ORGANIZATION_BASE_URI+"WESO");
		Resource webfoundation = model.createResource(TransformerAppServ.ORGANIZATION_BASE_URI+"webfoundation");
		Resource worldbank = model.createResource(TransformerAppServ.ORGANIZATION_BASE_URI+"WorldBank");
		int obsCounter = 0;
		for(ObservationTO observation:observations){
			CountryTO countryDecorated = observation.getCountryDecorated();			
			String code = null;
			String countryName = null;
			Resource uriArea = null;
			if(countryDecorated == null){
				code = TransformerAppServ.encodeNotCountry(observation.getCountry()); //FIXME
				countryName = code;
				uriArea = model.createResource(TransformerAppServ.REGION_BASE_URI+code);
			}else{
				code = countryDecorated.getCode();
				countryName = countryDecorated.getName();
				uriArea = model.createResource(observation.getCountryDecorated().toURI());
			}
			if(countryName.length()>2){//FIXME: SKIP missing regions
				String idIndicator=extracId(observation);
				String uri = TransformerAppServ.OBSERVATION_BASE_URI 
				+"external/obs"+(obsCounter++)
				;	

				Resource dataset = model.createResource(TransformerAppServ.DATASET_BASE_URI+"external/"+idIndicator);
				Resource indicator = model.createResource(TransformerAppServ.INDICATOR_BASE_URI+"external/"+hackId(observation));	

				Resource observationRDF = model.createResource(uri);		

				Resource status = model.createResource(TransformerAppServ.HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_CODE+observation.getStatus());	
				model.add(observationRDF, RDF.type, obs);

				String title = observation.getTitle().split("#")[1];

				//model.add(observationRDF,RDFS.label,TransformerAppServ.literalLang(model,idIndicator+" "+title,TransformerAppServ.LANG_EN));
				model.add(observationRDF,RDFS.comment,TransformerAppServ.literalLang(model,
						title+" in "+TransformerAppServ.prettyPrint(countryName)+" during "+observation.getYear(),TransformerAppServ.LANG_EN));
				model.addLiteral(observationRDF,DCTerms.date,Integer.valueOf(observation.getYear()));
				model.add(observationRDF,DCTerms.description,TransformerAppServ.literalLang(model,title,TransformerAppServ.LANG_EN));
				model.add(observationRDF,DCTerms.identifier,idIndicator);
				model.add(observationRDF,DCTerms.publisher,webfoundation);
				model.add(observationRDF,DCTerms.contributor,weso);
				model.add(observationRDF,DCTerms.creator,worldbank);
				model.add(observationRDF,model.getProperty(TransformerAppServ.ONTOLOGY_BASE_URI+"ref-indicator"),indicator);
				double value;
				try{
					value = Double.valueOf(observation.getValue());
					model.addLiteral(observationRDF,model.getProperty(TransformerAppServ.ONTOLOGY_BASE_URI+"value"),value);
					//FIXME: debug
					if(observation.getCountry().equals("US")){
						System.out.println(idIndicator+" "+observation.getValue()+" "+value+" "+
					model.listObjectsOfProperty(observationRDF, 
							model.getProperty(TransformerAppServ.ONTOLOGY_BASE_URI+"value")).next().asLiteral().getDouble());
					}
					
				}catch(java.lang.NumberFormatException e){
					//logger.warn("Resource: "+uri+" exception converting string "+observation+" to number, set to MISSING VALUE.");				
					status = model.createResource(TransformerAppServ.HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_CODE+StatusUtils.MISSING);					
				}catch(Exception e){
					//logger.warn("Resource: "+uri+" exception converting string "+observation+" to number, set to MISSING VALUE.");				
					status = model.createResource(TransformerAppServ.HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_CODE+StatusUtils.MISSING);					
				}
				model.addLiteral(observationRDF,model.getProperty(TransformerAppServ.ONTOLOGY_BASE_URI+"ref-year"),Integer.valueOf(observation.getYear()));
				model.add(observationRDF,model.getProperty(TransformerAppServ.ONTOLOGY_BASE_URI+"ref-area"),uriArea);
				model.add(observationRDF,model.getProperty(TransformerAppServ.HTTP_PURL_ORG_LINKED_DATA_SDMX_2009_CONCEPT+"obsStatus"),status);
				model.add(observationRDF,model.getProperty(TransformerAppServ.HTTP_PURL_ORG_LINKED_DATA_CUBE+"dataSet"),dataset);		
			}else{
				//logger.warn("Skipping observation  "+observation);
			}
		}
		completeModel.setObservations(model);
		return completeModel;
	}

	private String getId(String idIndicator) {
		return idIndicator;
	}

	private String hackId(ObservationTO observation) {
		return observation.getTitle().split("#")[0];
	}

	private String extracId(ObservationTO observation) {		
		return observation.getTitle().split("#")[0];
	}
}
